package com.dingreading.cloud.admin.service.impl;

import com.dingreading.cloud.admin.dto.CmservicesDto;
import com.dingreading.cloud.admin.entity.Cmservices;
import com.dingreading.cloud.admin.entity.table.CmservicesTableDef;
import com.dingreading.cloud.admin.mapper.CmservicesMapper;
import com.dingreading.cloud.admin.service.CmservicesService;
import com.dingreading.cloud.admin.util.ScheduleUtil;
import com.dingreading.cloud.common.util.EnumType;
import com.dingreading.cloud.common.util.QueryFiledUtil;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 服务层实现。
 *
 * @author Administrator
 * @since 2023-11-22
 */
@Service
public class CmservicesServiceImpl extends BaseServiceImpl<CmservicesMapper, Cmservices, CmservicesTableDef> implements CmservicesService {


    @Override
    protected CmservicesTableDef getTable() {
        return CmservicesTableDef.cmservices;
    }


    @Override
    public List<CmservicesDto> dtoListByOrderCode(String storeUid, String memberUid, String orderCode) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.memberUid.eq(memberUid))
                .and(table.orderCode.eq(orderCode));
        QueryWrapper where = QueryWrapper.create()
                .where(condition);
        return getMapper().selectListByQueryAs(where, CmservicesDto.class);
    }


    @Override
    public List<CmservicesDto> dtoListByOrderCodes(String storeUid, List<String> orderCodes) {
        QueryCondition condition = table.orderCode.in(orderCodes);
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        QueryWrapper where = QueryWrapper.create()
                .where(condition);
        return getMapper().selectListByQueryAs(where, CmservicesDto.class);
    }


    @Override
    public Cmservices getMemberConsumesService(List<String> storeUidList, String memberUid, String projectUid) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.in(storeUidList))
                .and(table.projectUid.eq(projectUid).or(table.projectUid.eq(ScheduleUtil.TIYAN_UID)))
                .and(table.memberUid.eq(memberUid))
                .and(table.leftLessons.gt(0))
                .and(table.lessonStatus.eq(1))
                .and(table.status.in(EnumType.ServiceStatus.PAUSE_CARD.getStatus(), EnumType.ServiceStatus.OPEN_CARD.getStatus()))
                .and(table.changeStatus.eq(EnumType.ServiceStatus.NO_CHANGE.getStatus()));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.orderCode.asc(), table.isGift.asc());
        return getMapper().selectOneByQuery(wrapper);
    }


    @Override
    public boolean haveProjectUid(String projectUid) {
        QueryCondition condition = table.projectUid.eq(projectUid);
        return exists(condition);
    }

    @Override
    public boolean haveProductUid(String productUid) {
        QueryCondition condition = table.productUid.eq(productUid);
        return exists(condition);
    }


    @Override
    public List<Cmservices> overdueListByCorpUidAndStatusAndEndDate(String corpUid, String beginDate, String endDate) {
        QueryCondition condition = table.corpUid.eq(corpUid)
                .and(table.status.eq(1))
                .and(table.endDate.between(beginDate, endDate));
        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.storeUid.asc(), table.endDate.asc());
        return getMapper().selectListByQuery(wrapper);
    }

    @Override
    public Map<String, List<Cmservices>> validNumMap(String corpUid, String endDate, List<String> memberUids) {
        QueryCondition condition = table.corpUid.eq(corpUid)
                .and(table.status.in(0, -1).or(table.status.eq(1).and(table.endDate.gt(endDate))))
                .and(table.memberUid.in(memberUids));

        List<Cmservices> list = getMapper().selectListByCondition(condition);

        Map<String, List<Cmservices>> map = new HashMap<>();
        if (CollectionUtils.isNotEmpty(list))
            map = list.stream().collect(Collectors.groupingBy(Cmservices::getMemberUid));

        return map;
    }

    @Override
    public List<CmservicesDto> dtoListByOrderCodesNotChangeOrRefund(String storeUid, List<String> orderCodes) {
        QueryCondition condition = table.orderCode.in(orderCodes)
                .and(table.status.isNotNull());
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        QueryWrapper where = QueryWrapper.create()
                .where(condition);
        return getMapper().selectListByQueryAs(where, CmservicesDto.class);
    }

    @Override
    public List<Cmservices> listByStoreUidInAndEndDateAndLeftLesson(List<String> storeUidList, String today) {
        int noCardStatus = EnumType.ServiceStatus.NO_CARD.getStatus();
        int openCardStatus = EnumType.ServiceStatus.OPEN_CARD.getStatus();
        int pauseCardStatus = EnumType.ServiceStatus.PAUSE_CARD.getStatus();

        String expType = EnumType.OrderType.EXP.getType();
        String giftType = EnumType.OrderType.GIFT.getType();
        String refundType = EnumType.OrderType.REFUND.getType();
        QueryCondition condition = QueryCondition.createEmpty()
                .and(table.storeUid.in(storeUidList))
                .and(table.orderType.notIn(expType, giftType, refundType))
                .and(table.changeStatus.eq(EnumType.ServiceStatus.NO_CHANGE.getStatus()))
                .and(table.status.eq(noCardStatus)
                        .or(table.status.in(openCardStatus, pauseCardStatus)
                                .and(table.totalLessons.gt(0).and(table.leftLessons.gt(0))
                                        .or(table.totalLessons.isNull().and(table.endDate.ge(today))))
                        )
                );
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public List<Cmservices> overdueMemberList(List<String> storeUidList, String beginDate, String endDate) {
        String refundType = EnumType.OrderType.REFUND.getType();
        QueryCondition condition = table.storeUid.in(storeUidList)
                .and(table.orderType.ne(refundType))
                .and(table.changeStatus.eq(EnumType.ServiceStatus.NO_CHANGE.getStatus()))
                .and(table.status.eq(EnumType.ServiceStatus.OPEN_CARD.getStatus()))
                .and(table.orderType.notIn(EnumType.OrderType.EXP.getType(), EnumType.OrderType.GIFT.getType(), EnumType.OrderType.REFUND.getType()))
                .and(table.totalLessons.gt(0).and(table.leftLessons.between(1, 4))
                        .or(table.totalLessons.isNull().and(table.endDate.between(beginDate, endDate)))
                );
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public List<Cmservices> amountSplitList(List<String> storeUidList, String beginDate, String endDate) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.in(storeUidList))
                .and(table.addTime.between(QueryFiledUtil.appendMin00(beginDate), QueryFiledUtil.appendMin24(endDate)))
                .and(table.changeStatus.eq(EnumType.ServiceStatus.NO_CHANGE.getStatus()))
                .and(table.totalAmount.isNull().or(table.totalAmount.eq(0)));

        return getMapper().selectListByCondition(condition);
    }

    @Override
    public List<Cmservices> listByOrderCodeAndType(String orderCode, boolean editOrder) {
        QueryCondition condition = table.orderCode.eq(orderCode);
        // 1:创建、更新、变更、退费使用，0:补充数据使用
        if (editOrder)
            condition.and(table.changeStatus.eq(EnumType.ServiceStatus.NO_CHANGE.getStatus()));
        else
            condition.and(table.changeStatus.eq(EnumType.ServiceStatus.NO_CHANGE.getStatus())
                    .or(table.changeStatus.eq(EnumType.ServiceStatus.INVALID.getStatus()))
            );
        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition);
        return getMapper().selectListByQuery(wrapper);
    }

    @Override
    public void updateAmount(String uid, double totalAmount, double unitAmount) {
        UpdateChain.of(Cmservices.class)
                .set(table.totalAmount, totalAmount)
                .set(table.unitAmount, unitAmount)
                .where(table.uid.eq(uid))
                .update();
    }

    @Override
    public List<Cmservices> listByMainSubjectUid(String mainSubjectUid) {
        return getMapper().selectListByCondition(table.mainSubjectUid.eq(mainSubjectUid));
    }

    @Override
    public void updateSubject(String uid, String subjectUid, String subjectName, String stageUid, String stageName) {
        UpdateChain.of(Cmservices.class)
                .set(table.subjectUid, subjectUid)
                .set(table.subjectName, subjectName)
                .set(table.stageUid, stageUid)
                .set(table.stageName, stageName)
                .where(table.uid.eq(uid))
                .update();
    }

}
